package com.heo.music.player.service.impl;

import com.heo.music.player.auth.UserInfoContextHolder;
import com.heo.music.player.converter.MusicInfoConverter;
import com.heo.music.player.converter.PlaylistConverter;
import com.heo.music.player.dao.MusicInfoDao;
import com.heo.music.player.dao.Playlist2MusicInfoDao;
import com.heo.music.player.dao.PlaylistDao;
import com.heo.music.player.dto.input.PlaylistInput;
import com.heo.music.player.dto.output.MusicInfoOutput;
import com.heo.music.player.dto.output.PlaylistOutput;
import com.heo.music.player.entity.MusicInfo;
import com.heo.music.player.entity.Playlist;
import com.heo.music.player.entity.Playlist2MusicInfo;
import com.heo.music.player.entity.UserInfo;
import com.heo.music.player.service.PlaylistService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;
import java.util.Optional;

/**
 * created on 2024-05-12 11:27
 *
 * @author 星天无极
 **/
@Service
@Slf4j
@RequiredArgsConstructor
public class PlaylistServiceImpl implements PlaylistService {

    private final PlaylistDao playlistDao;

    private final MusicInfoDao musicInfoDao;

    private final Playlist2MusicInfoDao playlist2MusicInfoDao;

    private final PlaylistConverter playlistConverter;

    private final MusicInfoConverter musicInfoConverter;

    @Override
    public PlaylistOutput createPlaylist(PlaylistInput input) {
        UserInfo userInfo = UserInfoContextHolder.getUserInfo();
        Playlist playlist = new Playlist();
        playlist.setTitle(input.getTitle());
        playlist.setUserInfo(userInfo);
        playlistDao.save(playlist);
        return playlistConverter.convert(playlist);
    }

    @Override
    public List<PlaylistOutput> getAllPlaylist() {
        UserInfo userInfo = UserInfoContextHolder.getUserInfo();
        List<Playlist> list = playlistDao.findAllByUserInfo(new UserInfo(userInfo.getId()));
        return playlistConverter.convert(list);
    }

    @Override
    public List<MusicInfoOutput> getMusicInfoInPlaylist(Integer playlistId) {
        Playlist playlistById = getPlaylistById(playlistId);
        List<MusicInfo> musicInfoList = playlist2MusicInfoDao.findMusicInfoByPlaylist(playlistById);
        return musicInfoConverter.convert(musicInfoList);
    }

    private Playlist getPlaylistById(Integer playlistId) {
        return playlistDao.findById(playlistId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "播放列表不存在"));
    }

    private MusicInfo getMusicInfoById(Integer musicId) {
        return musicInfoDao.findById(musicId).orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "音乐不存在"));
    }

    @Override
    public void addMusicInfoToPlaylist(Integer playlistId, Integer musicId) {
        Playlist playlist = getPlaylistById(playlistId);
        MusicInfo musicInfo = getMusicInfoById(musicId);
        if (!playlist2MusicInfoDao.existsByPlaylistAndMusicInfo(playlist, musicInfo)) {
            Playlist2MusicInfo playlist2MusicInfo = new Playlist2MusicInfo(playlist, musicInfo);
            playlist2MusicInfoDao.save(playlist2MusicInfo);
        }
    }

    @Override
    public void removeMusicInfoFromPlaylist(Integer playlistId, Integer musicId) {
        Playlist playlist = getPlaylistById(playlistId);
        MusicInfo musicInfo = getMusicInfoById(musicId);
        Optional<Playlist2MusicInfo> optional = playlist2MusicInfoDao.findByPlaylistAndMusicInfo(playlist, musicInfo);
        optional.ifPresent(playlist2MusicInfoDao::delete);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePlaylist(Integer playlistId) {
        Playlist playlist = getPlaylistById(playlistId);
        playlist2MusicInfoDao.deleteByPlaylist(playlist);
        playlistDao.delete(playlist);
    }
}
